package site.codeyin.javautils.controller.validate;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Date;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * @author <a href="https://github.com/liangcheng2221">yinjie</a>
 * @date 2024-09-07 15:52
 */
@Target({TYPE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {DateRangeValid.ValidateDate.class})
public @interface DateRangeValid {
    String message() default "开始时间不能大于结束时间";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * 返回开始时间的字段名称
     *
     * @return 返回开始时间的字段名称
     */
    String begin();

    /**
     * 返回结束时间的字段名称
     *
     * @return 返回结束时间的字段名称
     */
    String end();


    /**
     * 校验配置类
     */
    class ValidateDate implements ConstraintValidator<DateRangeValid, Object> {
        /**
         * 开始时间的字段名称
         */
        private String begin;
        /**
         * 返回结束时间的字段名称
         */
        private String end;

        @Override
        public void initialize(DateRangeValid constraintAnnotation) {
            begin = constraintAnnotation.begin();
            end = constraintAnnotation.end();
        }

        @Override
        public boolean isValid(Object value, ConstraintValidatorContext context) {
            try {
                if (value == null){
                    return true;
                }
                // 反射获取字段类的字段名称
                Field begin = value.getClass().getDeclaredField(this.begin);
                Field end = value.getClass().getDeclaredField(this.end);
                begin.setAccessible(true);
                end.setAccessible(true);

                Date beginTime =(Date) begin.get(value);
                Date endTime =(Date) end.get(value);

                if (beginTime == null || endTime == null || beginTime.equals(endTime)){
                    return true;
                }

                return endTime.after(beginTime);

            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
